/**
 * <pre>
 * 紫光软件系统有限公司广电事业部
 * Copyright (C): 2011
 * 
 * 文件名称：
 * com.unis.iptv.common.utils.Authentication.java
 * 
 * 文件描述: 
 * TODO 机顶盒认证类
 * 
 * Notes:
 * 修改历史(作者/日期/改动描述):
 * 杨飞宇/2011-8-3/初始化版本。
 * </pre>
 */
package com.unis.iptv.common.utils;

import static com.unis.iptv.client.ClientCustomContext.executeRequest;
import static com.unis.iptv.client.ClientCustomContext.getCustomContext;

import java.io.IOException;
import java.security.Security;
import java.util.Calendar;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * @date 2011-8-3
 * @author 杨飞宇
 */
public class Authentication {
	private static Log iptvCourse = LogFactory.getLog("iptvCourse");
	private static Log iptvErrCourse = LogFactory.getLog("iptvErrCourse");
	
	public static void main(String[] args) throws Exception {
		GlobalUtil.initConfiguration();
		Auth();
	}
	
	public static boolean Auth() throws Exception {
		try {
			String response;
			String AuthInfo = "";
			String Request;
			String ipAddress = "";
			String lastTermno = "";
			String UserToken = "";
			String baseUrl = "";
			String authUrl = "";
			String epgDomain = "";
			String baseDomain = "";
			String platformUrl = "";
			response = getCustomContext(GlobalUtil.authServer + "?UserID="
					+ GlobalUtil.stbAccount + "&Action=Login&Mode=MENU");
			String regex = "Authentication\\.CTCGetAuthInfo\\('(\\S+)'\\);.*<form action=\"(\\S+)\" name=\"authform\" method=\"post\">.*<input type=\"hidden\" name=\"StbIP\" value=\"(\\S+)\">.*<input type=\"hidden\" name=\"LastTermno\" value=\"(\\S+)\">";
			Pattern p = Pattern.compile(regex);
			Matcher m = p.matcher(response.replaceAll("\n", ""));
			if (m.find()) {
				AuthInfo = m.group(1);
				ipAddress = m.group(3);
				authUrl = m.group(2);
				lastTermno = m.group(4);
			} else {
				iptvErrCourse.error("Authentication.CTCGetAuthInfo not found.");
			}
			platformUrl = authUrl.substring(0, authUrl.lastIndexOf("/") + 1);
			Request = "UserID="
					+ GlobalUtil.stbAccount
					+ "&Authenticator="
					+ Authenticator(AuthInfo, GlobalUtil.stbNum,
							GlobalUtil.mac, ipAddress, GlobalUtil.stbAccount,
							GlobalUtil.stbPassword) + "&StbIP=" + ipAddress
					+ "&LastTermno=" + lastTermno;
			Request = Request.replace("@", "%40");
			response = getCustomContext(authUrl + "?" + Request).replaceAll(
					"\n", "");
			regex = "Authentication\\.CTCSetConfig\\('UserToken', '(\\S+)'\\);.*Authentication\\.CTCSetConfig\\('EPGDomain', '(\\S+)'\\);.*window\\.location = \"\\S+\";}";
			p = Pattern.compile(regex);
			m = p.matcher(response);
			if (m.find()) {
				UserToken = m.group(1);
				epgDomain = m.group(2);
			}
			baseDomain = epgDomain.substring(0, epgDomain.lastIndexOf("/") + 1);
			executeRequest(platformUrl + "getchannellist.jsp?UserToken="
					+ UserToken);
			executeRequest(platformUrl + "getservicelist.jsp");
			String authSucessUrl = epgDomain + "?UserToken=" + UserToken
					+ "&UserID=" + GlobalUtil.stbAccount + "&UserIP="
					+ ipAddress;
			iptvCourse.info("AuthSucess:" + authSucessUrl);
			executeRequest(authSucessUrl);
			executeRequest(baseDomain + "funcportalauth.jsp");
			executeRequest(baseDomain + "frameset_judger.jsp");
			executeRequest(baseDomain + "start_channel.jsp?tempno=16");
			baseUrl = authUrl.substring(0, authUrl.indexOf("/", 7));
			GlobalUtil.baseUrl = baseUrl;
			executeRequest(baseUrl + "/iptvepg/frame1008/portal.jsp");
			executeRequest(baseUrl + "/iptvepg/frame1008/frame_portal.jsp");
		} catch (IOException e) {
			iptvCourse.info("认证失败，3秒后重试！" + e.getMessage());
			return false;
		}
		return true;
	}
	
	private static String Authenticator(String AuthInfo, String StbId,
			String MacAddr, String IpAddr, String UserId, String Password) {
		String AuthStr = "";
		String Result = "";
		Random Rand = new Random(Calendar.getInstance().getTimeInMillis());
		AuthStr += String.format("%08d", Rand.nextInt(100000000)) + "$";
		AuthStr += AuthInfo + "$";
		AuthStr += UserId + "$";
		AuthStr += StbId + "$";
		AuthStr += IpAddr + "$";
		AuthStr += MacAddr + "$";
		AuthStr += "990070|$CTC";
		try {
			byte Auth[] = AuthStr.getBytes("ASCII");
			int Len = Auth.length;
			int Mod = Len % 8;
			
			if (Mod != 0)
				Len += 8 - Mod;
			byte AuthBytes[] = new byte[Len];
			
			for (int i = 0; i < Len; i++) {
				if (i >= Auth.length)
					AuthBytes[i] = (byte) (8 - Mod);
				else
					AuthBytes[i] = Auth[i];
			}
			
			String Algorithm = "DESede";
			byte KeyBytes[] = new byte[24];
			byte PassBytes[] = Password.getBytes();
			
			for (int i = 0; i < 24; i++) {
				if (i < PassBytes.length)
					KeyBytes[i] = PassBytes[i];
				else
					KeyBytes[i] = 0x30;
			}
			Security.addProvider(new com.sun.crypto.provider.SunJCE());
			SecretKey DesKey = new SecretKeySpec(KeyBytes, Algorithm);
			Cipher C = Cipher.getInstance(Algorithm);
			C.init(Cipher.ENCRYPT_MODE, DesKey);
			byte Encrypt[] = C.doFinal(AuthBytes);
			for (int i = 0; i < Len; i++) {
				Result += String.format("%02X",
						Encrypt[i] < 0 ? (256 + Encrypt[i]) : Encrypt[i]);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return Result;
	}
}
